/*
 * THE SOURCE CODES OF THE SOFTWARE ARE VALUABLE ASSETS OF FIDUS TECHNOLOGIES LTD.
 * YOU AGREE TO KEEP ALL SOURCE CODES OF THE SOFTWARE IN CONFIDENCE. YOU MAY NOT TRANSFER
 * OR ASSIGN THE SOFTWARE OR YOUR RIGHTS UNDER THIS AGREEMENT.
 * LIMITED WARRANTY
 * THE SOFTWARE AND ACCOMPANYING WRITTEN MATERIALS (INCLUDING INSTRUCTIONS FOR USE) ARE PROVIDED "AS IS"
 * AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. YOU ASSUME THE ENTIRE
 * RISK AS TO THE RESULTS AND PERFORMANCE OF THE SOFTWARE.
 * FIDUS TECHNOLOGIES DOES NOT WARRANT THAT THE SOFTWARE WILL MEET ALL YOUR REQUIREMENTS, THAT OPERATIONS
 * OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ALL SOFTWARE ERRORS WILL BE CORRECTED.
 * FIDUS TECHNOLOGIES-SOFTWARE SOLUTIONS IS NOT RESPONSIBLE FOR PROBLEMS CAUSED BY CHANGES IN THE
 * OPERATING CHARACTERISTICS OF COMPUTER HARDWARE OR COMPUTER OPERATING SYSTEMS WHICH ARE MADE AFTER
 * WHICH ARE MADE AFTER THE RELEASE OF THE SOFTWARE NOR FOR PROBLEMS IN THE INTERACTION OF THE SOFTWARE
 * WITH NON-FIDUS TECHNOLOGIES APPLICATION.WILL HAVE NO RESPONSIBILITY TO REPLACE OR REFUND THE LICENSE FEES
 * FOR MEDIA DAMAGED BY ACCIDENT, ABUSE OR MISAPPLICATION. THIS SOFTWARE IS INTENDED FOR COMMERCIAL,
 * INSTITUTIONAL, AND INDUSTRIAL USERS. THE ABOVE WARRANTIES ARE EXCLUSIVE AND IN LIEU OF ALL OTHER WARRANTIES,
 * WHETHER EXPRESSED OR IMPLIED, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NON-INFRINGEMENT. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY FIDUS TECHNOLOGIES,
 * ITS EMPLOYEES, DISTRIBUTORS, DEALERS OR AGENTS SHALL INCREASE THE SCOPE OF THE ABOVE WARRANTIES OR
 * CREATE ANY NEW WARRANTIES. NEITHER FIDUS TECHNOLOGIES NOR ANYONE ELSE WHO HAS BEEN INVOLVED IN THE
 * CREATION, PRODUCTION OR DELIVERY OF THE SOFTWARE SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL
 * OR INCIDENTAL DAMAGES (INCLUDING DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS LOSSES, BUSINESS
 * INTERRUPTION, LOSS OF DATA, AND THE LIKE) ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE,
 * OR ANY OTHER CLAIM BY ANY PARTY EVEN IF FIDUS TECHNOLOGIES HAS BEEN ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGES. IN THE EVENT FIDUS TECHNOLOGIES IS LIABLE FOR ANY DAMAGES, FIDUS TECHNOLOGIES' LIABILITY
 * FOR DAMAGES SHALL BE LIMITED TO THE AMOUNT PAID FOR THE SOFTWARE UNDER THE TERMS AND CONDITIONS OF THIS
 * AGREEMENT.
 * http://www.fidustechnologies.com
 * Copyright(C) 2010 FIDUS TECHNOLOGIES-Software Solutions(R)
 * All rights reserved.
 */

/*
 * LoginWindow.java
 *
 * Created on 2 Sep, 2010, 11:30:38 AM
 */
package com.fidus.inventory.login;

import com.fidus.inventory.UI.docking.MainScreen;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.List;
import javax.persistence.Query;
import javax.swing.JOptionPane;
import oracle.toplink.essentials.expressions.Expression;
import oracle.toplink.essentials.expressions.ExpressionBuilder;
import org.jdesktop.application.Action;
import org.jdesktop.application.Task;
import org.jdesktop.beansbinding.AbstractBindingListener;
import org.jdesktop.beansbinding.Binding;
import org.jdesktop.beansbinding.PropertyStateEvent;
import org.jdesktop.swingx.JXFrame;
import org.jdesktop.swingx.JXPanel;

/**
 * This is a login class. This will be a starting point of the application.
 * User will be authenticated on this screen. 
 * @author Mahesh Kedari<mahesh.kedari@fidustechnologies.com>
 */
public class LoginWindow extends JXFrame {

    private static LoginWindow dialog;

    /** Creates new form LoginWindow */
    public LoginWindow() {
        dialog = this;
        initComponents();
        setVisible(true);

        /* Binding Listener is added to listen the value changed in JTextBox or
         * JPasswordField. This is required to decide the status of Login
         * button. If nothing is enterd in any of the input area, the Login
         * button will be kept disabled.
         */
        bindingGroup.addBindingListener(new AbstractBindingListener() {

            @Override
            public void targetChanged(Binding binding, PropertyStateEvent event) {
                if (userNameTextField.getText().equals("") || String.valueOf(userPasswordField.getPassword()).equals("")) {
                    setLoginAllowed(false);
                } else {
                    setLoginAllowed(true);
                }
            }
        });
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("inventorymanagement_dbPU").createEntityManager();
        jXPanel1 = new JXPanel(){
            @Override
            public void paintComponent(java.awt.Graphics g) {
                try {
                    java.awt.Image img = javax.imageio.ImageIO.read(new java.net.URL(getClass().getResource("LoginBg.jpg"), "LoginBg.jpg"));
                    //super.paintComponent(g);
                    if (img != null) {
                        g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        };
        userNameTextField = new javax.swing.JTextField();
        userPasswordField = new javax.swing.JPasswordField();
        passwordLabel = new javax.swing.JLabel();
        userNameLabel = new javax.swing.JLabel();
        loginButton = new javax.swing.JButton();
        clearButton = new javax.swing.JButton();
        closeButton = new javax.swing.JButton();
        titleLabel = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        copyrightsLabel = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setStartPosition(org.jdesktop.swingx.JXFrame.StartPosition.CenterInScreen);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(simple_inventory.Simple_InventoryApp.class).getContext().getResourceMap(LoginWindow.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N
        setUndecorated(true);

        jXPanel1.setName("jXPanel1"); // NOI18N

        userNameTextField.setName("userNameTextField"); // NOI18N

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${applicationUser.userName}"), userNameTextField, org.jdesktop.beansbinding.BeanProperty.create("text"));
        bindingGroup.addBinding(binding);

        userPasswordField.setName("userPasswordField"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${applicationUser.userPassward}"), userPasswordField, org.jdesktop.beansbinding.BeanProperty.create("text"));
        bindingGroup.addBinding(binding);

        passwordLabel.setText(resourceMap.getString("passwordLabel.text")); // NOI18N
        passwordLabel.setName("passwordLabel"); // NOI18N

        userNameLabel.setText(resourceMap.getString("userNameLabel.text")); // NOI18N
        userNameLabel.setName("userNameLabel"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(simple_inventory.Simple_InventoryApp.class).getContext().getActionMap(LoginWindow.class, this);
        loginButton.setAction(actionMap.get("login")); // NOI18N
        loginButton.setText(resourceMap.getString("loginButton.text")); // NOI18N
        loginButton.setName("loginButton"); // NOI18N

        clearButton.setAction(actionMap.get("clear")); // NOI18N
        clearButton.setText(resourceMap.getString("clearButton.text")); // NOI18N
        clearButton.setName("clearButton"); // NOI18N

        closeButton.setAction(actionMap.get("close")); // NOI18N
        closeButton.setText(resourceMap.getString("closeButton.text")); // NOI18N
        closeButton.setName("closeButton"); // NOI18N

        titleLabel.setFont(resourceMap.getFont("titleLabel.font")); // NOI18N
        titleLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        titleLabel.setText(resourceMap.getString("titleLabel.text")); // NOI18N
        titleLabel.setName("titleLabel"); // NOI18N

        jSeparator1.setName("jSeparator1"); // NOI18N

        copyrightsLabel.setFont(resourceMap.getFont("copyrightsLabel.font")); // NOI18N
        copyrightsLabel.setText(resourceMap.getString("copyrightsLabel.text")); // NOI18N
        copyrightsLabel.setName("copyrightsLabel"); // NOI18N

        javax.swing.GroupLayout jXPanel1Layout = new javax.swing.GroupLayout(jXPanel1);
        jXPanel1.setLayout(jXPanel1Layout);
        jXPanel1Layout.setHorizontalGroup(
            jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(titleLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE)
            .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE)
            .addGroup(jXPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(copyrightsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 303, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(67, Short.MAX_VALUE))
            .addGroup(jXPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(userNameLabel)
                    .addComponent(passwordLabel)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jXPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(loginButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
                .addGroup(jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jXPanel1Layout.createSequentialGroup()
                        .addGap(39, 39, 39)
                        .addComponent(clearButton)
                        .addGap(54, 54, 54)
                        .addComponent(closeButton))
                    .addGroup(jXPanel1Layout.createSequentialGroup()
                        .addGap(11, 11, 11)
                        .addGroup(jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(userPasswordField, javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(userNameTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addContainerGap(72, Short.MAX_VALUE))
        );
        jXPanel1Layout.setVerticalGroup(
            jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jXPanel1Layout.createSequentialGroup()
                .addComponent(titleLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(userNameLabel)
                    .addComponent(userNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(28, 28, 28)
                .addGroup(jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(passwordLabel)
                    .addComponent(userPasswordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(jXPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(loginButton)
                    .addComponent(closeButton)
                    .addComponent(clearButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 14, Short.MAX_VALUE)
                .addComponent(copyrightsLabel))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jXPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jXPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        bindingGroup.bind();

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new LoginWindow();
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton clearButton;
    private javax.swing.JButton closeButton;
    private javax.swing.JLabel copyrightsLabel;
    private javax.persistence.EntityManager entityManager;
    private javax.swing.JSeparator jSeparator1;
    private org.jdesktop.swingx.JXPanel jXPanel1;
    private javax.swing.JButton loginButton;
    private javax.swing.JLabel passwordLabel;
    private javax.swing.JLabel titleLabel;
    private javax.swing.JLabel userNameLabel;
    private javax.swing.JTextField userNameTextField;
    private javax.swing.JPasswordField userPasswordField;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables
    private int invalidAttempt = 0;
    public ApplicationUser getLoggedInUser() {
        return applicationUser;
    }
    protected ApplicationUser applicationUser= new ApplicationUser();
    public static final String PROP_APPLICATIONUSER = "applicationUser";

    /**
     * Get the value of applicationUser
     *
     * @return the value of applicationUser
     */
    public ApplicationUser getApplicationUser() {
        return applicationUser;
    }

    /**
     * Set the value of applicationUser
     *
     * @param applicationUser new value of applicationUser
     */
    public void setApplicationUser(ApplicationUser applicationUser) {
        ApplicationUser oldApplicationUser = this.applicationUser;
        this.applicationUser = applicationUser;
        propertyChangeSupport.firePropertyChange(PROP_APPLICATIONUSER, oldApplicationUser, applicationUser);
    }
    protected boolean loginAllowed;
    public static final String PROP_LOGINALLOWED = "loginAllowed";

    /**
     * Get the value of loginAllowed
     *
     * @return the value of loginAllowed
     */
    public boolean isLoginAllowed() {
        return loginAllowed;
    }

    /**
     * Set the value of loginAllowed
     *
     * @param loginAllowed new value of loginAllowed
     */
    public void setLoginAllowed(boolean loginAllowed) {
        boolean oldLoginAllowed = this.loginAllowed;
        this.loginAllowed = loginAllowed;
        propertyChangeSupport.firePropertyChange(PROP_LOGINALLOWED, oldLoginAllowed, loginAllowed);
    }

    /**
     * Login Action Map. This function work as an action when user clicks on Login
     * button. Enabled property PROP_LOGINALLOWED will enable the button only
     * if both, user id and password fields are filled up by user. If they are
     * empty, this button will be disabled.
     */
    @Action(enabledProperty = "loginAllowed")
    public Task login() {
        return new LoginTask(org.jdesktop.application.Application.getInstance());
    }

    private class LoginTask extends org.jdesktop.application.Task<Object, Void> {

        Boolean successful = false;

        LoginTask(org.jdesktop.application.Application app) {
            super(app);

        }

        @Override
        protected Object doInBackground() {
            /* Expresion Builder is used for a creating a query builder on Application User class */
            ExpressionBuilder expressionBuilder = new ExpressionBuilder(ApplicationUser.class);
            /* This expression will query on given user name */
            Expression expression1 = expressionBuilder.get("userName").equalsIgnoreCase(applicationUser.getUserName());
            /* This expression will query on given password */
            Expression expression2 = expressionBuilder.get("userPassward").equal(String.valueOf(userPasswordField.getPassword()));
            /* This expression will combine expression 1 and expression 2 */
            Expression expression = expression1.and(expression2);
            /* query is created for expression */
            Query query = ((oracle.toplink.essentials.ejb.cmp3.EntityManager) entityManager.getDelegate()).createQuery(expression, ApplicationUser.class);
            /* Getting the resultset for the query */
            List<ApplicationUser> userList = query.getResultList();
            /* Here we are checking if the query returned any result */

            if (userList.isEmpty()) {
                /* No result is returned. Authentication Failed */
                JOptionPane.showMessageDialog(null, "Failed to authenticate The user", "Inventory Management", JOptionPane.ERROR_MESSAGE);
                /* Here we are checking number of invalid attempts
                * If user enters invalid login credentials 3 times, 
                * application will exit
                */
                if(++invalidAttempt==3){
                    System.exit(0);
                }
            }else{
                JOptionPane.showMessageDialog(null, "Authentication Granted", "Inventory Management", JOptionPane.PLAIN_MESSAGE);
                /* Initialise the main window of application */
                new MainScreen(applicationUser);
                successful = true;                
            }

            return null;  // return your result
        }

        @Override
        protected void finished() {
            /* Check if authentication is completed successfully */
            if (successful) {
                /* Dispose Login dialog box */
                dialog.dispose();
            }
        }
    }

    /**
     * Clear action will clear the form.
     */
    @Action
    public void clear() {
        /* Form Reset */
        userNameTextField.setText("");
        userPasswordField.setText("");        
    }

    /**
     * Close Action will close the program after confirmation from the user.
     */
    @Action
    public void close() {
        /* Ask user for confirmation */
        int choice = JOptionPane.showConfirmDialog(null, "Are You Sure You Want to close Application?", "Inventory Manager", JOptionPane.YES_NO_OPTION);
        if (choice == JOptionPane.YES_OPTION) {
            /* If user choice is YES, Terminate the application */
            System.exit(0);
        }
    }
    private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    /**
     * Add PropertyChangeListener.
     * This will be listening to the changes in Properties, such as
     * loginAllowed, applicationUser.
     *
     * @param listener
     */
    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    /**
     * Remove PropertyChangeListener.
     *
     * @param listener
     */
    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }
}
